package cn.anlab.anappframe.net.sub2;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

import android.util.Log;

public class TCPConnection implements IConnection {

	private static final int PREFIX_BUFFER_LENGTH = 4;			//报文前缀的长度
	
	private InetSocketAddress address;
	private IHandler handler;
	private Selector selector;
	private SocketChannel channel;

	public TCPConnection(InetSocketAddress address, IHandler handler) {
		this.address = address;
	}

	@Override
	public void connect() throws IOException {
		
		channel = SocketChannel.open();
		channel.configureBlocking(false);
		channel.connect(address);
		
		if (selector == null || ! selector.isOpen()) {
			selector = Selector.open();			
		}
		channel.register(selector, SelectionKey.OP_CONNECT);
		
		for (;;) {
			selector.select();
			Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
			while (keyIterator.hasNext()) {
				SelectionKey key = keyIterator.next();
				keyIterator.remove();
				// 连接事件
				if (key.isConnectable()) {
					Log.d("anlog", "key.isConnectable()");
					SocketChannel socketChannel = (SocketChannel) key.channel();
					if (socketChannel.isConnectionPending())
						socketChannel.finishConnect();
					socketChannel.register(selector, SelectionKey.OP_READ);
				}
				//读事件
				if (key.isReadable()) {
					receive(key);
				}
			}
		}
		
	}

	@Override
	public void disconnect() throws IOException {
		if(channel != null) {
			channel.close();
			channel = null;
		}
	}
	
	/**
	 * 判断是否已经连接
	 * @return
	 */
	public boolean isConnected() {
		if(channel != null) {
			return channel.isConnected();
		}
		return false;
	}

	@Override
	public void send(byte[] data) throws IOException {
		if(isConnected()) {
			int length = PREFIX_BUFFER_LENGTH + data.length;
			ByteBuffer buff = ByteBuffer.allocate(length);
			buff.putInt(data.length);
			buff.put(data);
			buff.flip();
			channel.write(buff);
			buff.clear();
		}
	}
	
	public void receive(SelectionKey key) throws IOException {
		Log.d("anlog", "key.isReadable()");
		SocketChannel socketChannel = (SocketChannel) key.channel();
		//获取报文的长度
		ByteBuffer prefixBuff = ByteBuffer.allocate(PREFIX_BUFFER_LENGTH);
		int readSize0 = socketChannel.read(prefixBuff);
		if (readSize0 < PREFIX_BUFFER_LENGTH) {
			key.cancel();
		}
		prefixBuff.flip();
		int length = prefixBuff.asIntBuffer().get();
		prefixBuff.clear();
		//读取报文正文内容
		ByteBuffer byteBuffer = ByteBuffer.allocate(length);
		int readSize = socketChannel.read(byteBuffer);
		if(readSize != length) {
			System.out.println("报文长度不对！");
			handler.onError(new RuntimeException("Read size is not right."));
		}
		//处理响应
		byteBuffer.flip();
		byte[] bytes = byteBuffer.array();
		handler.onReceive(bytes);
		byteBuffer.clear();
	}

	@Override
	public void setHandler(IHandler handler) {
		this.handler = handler;
	}

	@Override
	public void setAddress(InetSocketAddress address) {
		this.address = address;
	}

}
